/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.
 */

package jdbcmanager.dbtools.agentwise;

import java.util.*;
import java.sql.*;

import javax.swing.tree.DefaultMutableTreeNode;

import jdbcmanager.dbtools.datatypes.*;

/**
 * Most part of the information is related to the Catalogs (databases) and their components:
 * <ul>
 * <li>Tables
 * <li>Relations among tables
 * <li>Indices
 * <li>Stored Procedures
 * <li>User Defined Types
 * </ul>
 * <p>
 * There is a default implementation of this interface named <code>DefaultAgentMetaData</code>.<br>
 * As this default implementation provides all needed functionality instead of implementing this interface, it is much appropiate to
 * simply inherits from <code>DefaultAgentMetaData</code> (if it were needed to modify its behaviour) than starting from zero by
 * implementing this interface. <br>
 * In fact, the default implementation can be used for all properly built JDBC drivers. But unfortunatelly not all JDBC drivers work
 * as espected.
 * <p>
 * For these "not educated" drivers, and to make things easier, specialized MetaData Agents can be created by extending (inheriting)
 * the default implementation.
 * <p>
 * Agents (see SqlAgentable and SqlAgentAnsi92 classes) will return the appropiate instance of a MetaDataExplorer according with the
 * DBMS it is designed to work with.
 * <p>
 * Note: This application works with only one driver at a time, and therefore, there is only one MetaData Agent per driver. <br>
 * Thus the same MetaData can be used by all DataBases in the server (DBMS) and by all tables in all DataBases.
 * 
 * @author Francisco Morero Peyrona
 */

public interface AgentMetaData
{
    /**
     * 
     * @param dbmd
     */
    public void setMetaData( DatabaseMetaData dbmd );

    /**
     * Retrieves Catalogs in DBMS.
     * <p>
     * It will return an array with all catalog names or an empty array if something goes wrong.
     * 
     * @return Catalogs in a DBMS
     */
    public String[] getCatalogs();

    /**
     * Checks if a table exists in a Catalog.
     * <p>
     * Note1: Diagram ("hidden") table is included in the search. <br>
     * Note2: It is assumed that there can not exist more that one table with same name in a Catalog and Schema. <br>
     * Note3: Table type is ignored and therefore is not used to narrow the search.
     * 
     * @param table  An instance of <code>DbEntityDescriptor</code>
     * @return <code>true</code> if the table described by passed argument exists, otherwise returns <code>false</code>
     * @throws SQLException  Thrown if an SQL error occurs
     */
    public boolean existsTable( DbEntityDescriptor table );

    /**
     * Removes hidden table(s).
     * <p>
     * Right now, the only hidden table is <code>Constant.sDIAGRAM_TABLE</code>
     * 
     * @param aTable  An array of <code>DbEntityDescriptor</code> instances
     * @return Another array as the one recieved without the hidden table(s)
     */
    public DbEntityDescriptor[] removeHiddenTables( DbEntityDescriptor[] aTable );

    /**
     * Removes hidden table(s).
     * <p>
     * Right now, the only hidden table is <code>Constant.sDIAGRAM_TABLE</code>
     * 
     * @param aTable  An array of <code>DefaultMutableTreeNode</code> instances
     * @return The same array as recieved without the hidden table(s)
     */
    public DefaultMutableTreeNode[] removeHiddenTables( DefaultMutableTreeNode[] aTable );

    /**
     * Retrieves an array of <code>DbEntityDescriptor</code> with table names.
     * 
     * @see DatabaseMetaData.getTables(...)
     */
    public DbEntityDescriptor[] getTables( String sCatalog, String sSchemaPattern, String sTableNamePattern, String[] asType );

    /**
     * Retrieves an array of <code>DefaultMutableTreeNode</code> instances. containing all tables of all types for desired catalog
     * and schema. <br>
     * <p>
     * Creates the best possible tree: if the DBMS (and JDBC driver) support table-types, they are used; if not, the tree will
     * contain only table names.
     * <p>
     * The method returns an array of <code>DefaultMutableTreeNode</code> instances. <br>
     * These nodes (and its childs if any) will be added to the "Tables" node in the tree.
     * <p>
     * Each SqlAgent can decide (by inheriting from this class) how the information will be presented. <br>
     * e.g. <code>DefaultMetaDataExplorer</code> provides Schema nodes, under the Schema nodes there are TableType nodes and under
     * them there are the tables themselves.
     * <p>
     * If SqlAgents are inherited from <code>DefaultMetaDataExplorer</code> (recommended), they can use, to facilitate their job,
     * following methods: <br>
     * <ul>
     * <li>getTableTree( String sCatalog )
     * <li>getTableTree( String sCatalog, String sSchema, String[] asTableType )
     * <li>getTableTree( String sCatalog, String sSchema, String sTableType )
     * <li>getTableTypes()
     * </ul>
     * 
     * @param sCatalog  The catalog name (or null)
     * @param sSchema   The schema name (or null)
     * @return An array of <code>DefaultMutableTreeNode</code> instances representing the hierarchical structure of the tables.
     */
    public DefaultMutableTreeNode[] getTableTree( String sCatalog, String sSchema );

    /**
     * Retrieves table structure (all table field columns).
     * 
     * @param table  An instance of <code>DbEntityDescriptor</code>
     * @return Table structure (all table field columns)
     */
    public TableColumnDefinition[] getTableColumns( DbEntityDescriptor table );

    /**
     * Retrieves all indices associated with a table.
     * 
     * @param table An instance of <code>DbEntityDescriptor</code>
     * @return All indices associated with a table
     */
    public IndexDefinition[] getTableIndices( DbEntityDescriptor table );

    /**
     * Retrieves imported relations for a table.
     * 
     * @param table An instance of <code>DbEntityDescriptor</code>
     * @return Relations for a table
     */
    public RelationDefinition[] getTableImportedRelations( DbEntityDescriptor table );

    /**
     * Retrieves imported relations for a table.
     * 
     * @param table  An instance of <code>DbEntityDescriptor</code>
     * @return Relations for a table
     */
    public RelationDefinition[] getTableExportedRelations( DbEntityDescriptor table );

    /**
     * Retrieves desired stored procedure.
     * 
     * @param ded An instance of <code>DbEntityDescriptor</code>
     * @return Stored Procedure as described in DbEntityDescriptor or <code>null</code> if does not exists
     * @throws SQLException  Thrown if an SQL error occurs
     */
    public StoredProcedureDefinition getProcedure( DbEntityDescriptor ded );

    /**
     * Retrieves all "Stored Procedure" names.
     * <p>
     * It will return one of following: <br>
     * <ul>
     * <li>An array with all stored procedures as instances of <code>DbEntityDescriptor</code>
     * <li>An empty array if DBMS supports stored procedures but there is none defined
     * <li><code>null</code> If DBMS does not supports stored procedures
     * </ul>
     * 
     * @param sCatalog  The catalog name
     * @return All stored procedures for designed catalog and schema
     */
    public DefaultMutableTreeNode[] getProcedureTree( String sCatalog, String sSchema );

    /**
     * Retrieves desired "User Defined Types"
     * 
     * @param ded  An instance of DbEntityDescriptor
     * @return User Defined Types for designed catalog, schema and name as described in DbEntityDescriptor or <code>null</code> if
     *         does not exists
     * @throws SQLException  Thrown if an SQL error occurs
     */
    public UDTDefinition getUDT( DbEntityDescriptor ded );

    /**
     * Retrieves all "User Defined Type" names.
     * <p>
     * It will return one of following: <br>
     * <ul>
     * <li>An array with all UDTs as instances of <code>DbEntityDescriptor</code>
     * <li>An empty array if DBMS there is none defined
     * <li><code>null</code> If DBMS does not supports stored procedures or an error happen
     * </ul>
     * 
     * @param sCatalog  The catalog name
     * @return All UDTs for designed catalog and schema
     */
    public DefaultMutableTreeNode[] getUDTTree( String sCatalog, String sSchema );

    /**
     * Retrieves the hierarchical structure of the diagrams.
     * <p>
     * It will return one of following: <br>
     * <ul>
     * <li>An array with all Diagrams as instances of <code>DbEntityDescriptor</code>
     * <li>An empty array if DBMS there is none defined
     * <li><code>null</code> If an error happen
     * </ul>
     * 
     * @param sCatalog  The catalog name (or null)
     * @param sSchema   The schema name (or null)
     * @return An array of <code>DefaultMutableTreeNode</code> instances representing the hierarchical structure of the diagrams.
     */
    public DefaultMutableTreeNode[] getDiagramTree( String sCatalog, String sSchema );

    /**
     * Retrieves an array where each element is one of the extra SQL keywords recognized by the DBMS.
     * 
     * @return An array where each element is one of the extra SQL keywords of the DBMS or an empty array if an error occurs
     */
    public String[] getExtraSQLKeywords();

    /**
     * Retrieves a Hashtable where keys are functions groups and the associated objects are String[] with one function per element
     * of the array.
     * 
     * @return A Hashtable with functions
     * @throws SQLException  Thrown if an SQL error occurs.
     */
    public Hashtable getPrebuiltFunctions();

    /**
     * Retrieves the database vendor's preferred term for "catalog".
     * 
     * @return database vendor's preferred term for "catalog".
     */
    public String getCatalogTerm();

    /**
     * Retrieves the database vendor's preferred term for "schema".
     * 
     * @return database vendor's preferred term for "schema".
     */
    public String getSchemaTerm();

    /**
     * Retrieves the database vendor's preferred term for "procedure".
     * 
     * @return database vendor's preferred term for "procedure".
     */
    public String getProcedureTerm();

    /**
     * 
     * @return
     */
    public String getDatabaseProductName();

    /**
     * 
     * @return
     */
    public String getDatabaseProductVersion();

    /**
     * 
     * @return
     */
    public String getDatabaseMajorVersion();

    /**
     * 
     * @return
     */
    public String getDatabaseMinorVersion();

    /**
     * 
     * @return
     */
    public String getDriverName();

    /**
     * 
     * @return
     */
    public String getDriverVersion();

    /**
     * 
     * @return
     */
    public String getDriverMajorVersion();

    /**
     * 
     * @return
     */
    public String getDriverMinorVersion();

    /**
     * 
     * @return
     */
    public String getJDBCMajorVersion();

    /**
     * 
     * @return
     */
    public String getJDBCMinorVersion();

    /**
     * Return A string array with all Schemas for this DBMS. Or an empty one if Schemas are not supported.
     * 
     * @return A string array with all Schemas for this DBMS.
     */
    public String[] getSchemas();

    /**
     * Return a string array containing the different types of tables in this database. E.G.
     * <code>"TABLE", "VIEW", "SYSTEM TABLE"</code>, or an empty array if table types are not supported.
     * 
     * @return table type names.
     */
    public String[] getTableTypes();

    /**
     * 
     * @param sCatalog
     * @param sSchema   The schema inside the catalog (can be <code>null</code>)
     * @param sTable    Table name
     * @return 
     * @throws  SQLException Thrown if an SQL error occurs
     */
    public ResultSet getColumns( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sSchema
     * @param sTable
     * @return 
     * @throws SQLException
     */
    public ResultSet getPrimaryKeys( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return 
     * @throws SQLException Thrown if an SQL error occurs
     */
    public ResultSet getImportedKeys( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return
     * @throws SQLException Thrown if an SQL error occurs
     */
    public ResultSet getExportedKeys( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return
     * @throws SQLException Thrown if an SQL error occurs
     */
    public ResultSet getIndices( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return 
     * @throws  SQLException Thrown if an SQL error occurs
     */
    public ResultSet getRowIDs( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return 
     * @throws SQLException Thrown if an SQL error occurs
     */
    public ResultSet getTablePrivileges( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return 
     * @throws SQLException Thrown if an SQL error occurs
     */
    public ResultSet getColumnPrivileges( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @param sCatalog
     * @param sTable
     * @return 
     * @throws SQLException Thrown if an SQL error occurs
     */
    public ResultSet getVersions( String sCatalog, String sSchema, String sTable ) throws SQLException;

    /**
     * 
     * @return 
     * @throws SQLException
     */
    public ResultSet getTypeInfo() throws SQLException;

    /**
     * 
     * @return
     */
    public boolean supportsStoredProcedures();

    /**
     * 
     * @return
     */
    public boolean supportsSchemasInDataManipulation();

    /**
     * 
     * @return
     */
    public boolean supportsCatalogsInDataManipulation();

    /**
     * 
     * @return
     */
    public boolean isCatalogAtStart();

    /**
     * 
     * @return
     */
    public String getCatalogSeparator();

    /**
     * 
     * @return
     */
    public String getIdentifierQuoteString();

    /**
     * 
     * @return
     */
    public String getExtraNameCharacters();

    /**
     * 
     * @return
     */
    public int getMaxCatalogNameLength();

    /**
     * 
     * @return
     */
    public int getMaxSchemaNameLength();

    /**
     * 
     * @return
     */
    public int getMaxTableNameLength();

    /**
     * 
     * @return
     */
    public int getMaxColumnNameLength();

    /**
     * 
     * @return
     */
    public int getMaxDiagramNameLength();

    /**
     * 
     * @return
     */
    public int getMaxProcedureNameLength();

    /**
     * 
     * @return
     */
    public int getMaxRowSize();

    /**
     * 
     * @return
     */
    public int getMaxColumnsInIndex();

    /**
     * 
     * @return
     */
    public boolean storesLowerCaseIdentifiers();

    /**
     * 
     * @return
     */
    public boolean storesMixedCaseIdentifiers();

    /**
     * 
     * @return
     */
    public boolean storesUpperCaseIdentifiers();

    /**
     * Return an array with all supported type for this Database.
     * <p>
     * Please check the implementation of this method in <code>DbMetadataWrapper</code> class
     * and also <code>AgentMetaDataOracle</code> class.
     * 
     * @return An array with all supported type for this Database
     */
    public TableColumnTypeDefinition[] getSupportedColumnTypes();

    /**
     * Maps specific database column types (like ROWID or CLOB) to the most similiar standard type.
     * <br>
     * This method should be overwritten in the specific agents
     * 
     * @param Database  specific column Type
     * @return Standard column Type
     */
    public int mapType( int nColumnType );
}